<?php

/*
	Class: Commerce_Cache

	About: Author
		Rich Joslin

	About: License
		<http://communit.as/docs/license>

	About: See Also
		Zend_Registry
*/
class Commerce_Cache {
	
	public $_factory = false;
	
	private $hosts = NULL;
	private $host_name = NULL;

	function __construct() {
		$frontendOptions = array();
		$frontendOptions['lifetime'] = Cts_Registry::get('cache_lifetime', 'commerce');
		$frontendOptions['automatic_serialization'] = true;
		$cache_dir = Zend_Registry::get('basepath').Cts_Registry::get('cache_folder', 'commerce');
		if (!is_dir($cache_dir)) {
			mkdir($cache_dir, 0777, true);
		}
		$backendOptions = array(
			'cache_dir' => $cache_dir,
			'hashed_directory_level' => '2',
			// 'hashed_directory_umask' => '0777',
			// TODO - why doesn't any of this work as expected?
			// 'cache_file_umask' => '0777',
			// 'file_locking' => false,
		);
		
		$this->_factory = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
		
		$this->host_name = Cts_Registry::get('host_id');
		$this->cleaningLady();
		
		return $this;
	}
	
	public function __get( $name ){
		if( $name=='factory' ){
			## Forces the use of this class (and it's __call method) to access the factory
			return $this;
		} else {
			return $this->{$name};
		}
	}
	
	public function __call( $name, $args ){
		if( $name=='clean' ){
			$this->forCleaningLady( $args );
		}
		
		if( $name=='save' ){
			$_lifetime = Cts_Registry::get('cache_lifetime', 'commerce');
			$lifetime = rand(($_lifetime*0.8),($_lifetime*1.2));
			$this->_factory->setOption('lifetime',$lifetime);
		}
		
		return call_user_func_array( array($this->_factory, $name), $args );
	}
	
	protected function forCleaningLady( $args ){
		if(is_null($this->host_name)) return;
		
		memory_profiler("start Cleaning Lady Preperation");
		
		$args = serialize($args);
		$hosts_table = new Hosts();
		$cache_table = new Dirtycache();
		
		if( is_null($this->hosts) ){
			$this->hosts = $this->getOtherHosts( $this->host_name, $hosts_table );
		}
		
		if( is_array($this->hosts) ){
			if( count($this->hosts) >= 1 ){
				$cache_table->delete("arguments = '{$args}'");
			
				foreach( $this->hosts as $host ){
					Cts_Log::report("Cache Clean :: Adding a record for the {$host['host_id']} cleaning lady", NULL, Zend_Log::INFO);
					$cache_table->insert(array(
						'host_id' => $host['host_id'],
						'arguments' => $args,
						'created_on' => date(DB_DATETIME_FORMAT),
					));
				}
			}
		}
		
		memory_profiler("end Cleaning Lady Preperation");
	}
	
	protected function cleaningLady(){
		if(is_null($this->host_name)) return;
		
		memory_profiler("start Cleaning Lady");
		
		$hosts_table = new Hosts();
		$cache_table = new Dirtycache();
		
		$this->addHost( $this->host_name, $hosts_table );
		
		$entries = $cache_table->fetchAllArray( $cache_table->select()->where("host_id = ?", $this->host_name) );
		
		if( count($entries)>=1 ){
			Cts_Log::report("Cache Cleaning Lady :: Updating ".count($entries)." remote cache cleans", NULL, Zend_Log::INFO);
			
			foreach( $entries as $cache ){
				$args = unserialize($cache['arguments']);
				call_user_func_array( array($this->_factory, 'clean'), $args );
			}
			
			$cache_table->delete("host_id = '{$this->host_name}'");
		}
		
		memory_profiler("end Cleaning Lady");
	}
	
	protected function getOtherHosts( $host_name, &$table ){
		$this->addHost( $host_name, $table );
		
		return $table->fetchAllArray( $table->select()->where("host_id != ?", $host_name) );
	}
	
	protected function addHost( $host_name, &$table ){
		$host_entered = $table->fetchAllArray( $table->select()->where("host_id = ?", $host_name) );
		
		if( count($host_entered)<=0 ){
			$table->insert(array(
				'host_id' => $host_name,
				'created_on' => date(DB_DATETIME_FORMAT),
			));
		}
	}
}
